package com.example.zhanghehe.myapplication.opengl3

import android.opengl.GLES30
import android.util.Log
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer

class Cube {

    private var mVertices: FloatBuffer

    private var mProgramObject: Int = 0

    constructor(){
        mVertices=ByteBuffer.allocateDirect(mVerticesData.size*4)
            .order(ByteOrder.nativeOrder())
            .asFloatBuffer()
            .put(mVerticesData)
        mVertices.position(0)

        val vertexShader=OpenGl3Render.loadShader(GLES30.GL_VERTEX_SHADER, vShaderStr)
        val fragmentShader=OpenGl3Render.loadShader(GLES30.GL_FRAGMENT_SHADER, fShaderStr)

        val programObject=GLES30.glCreateProgram()
        val linked=IntArray(1)


        if (programObject==0) {
            Log.e(TAG,"some kind of error, but what ?")
            return
        }

        GLES30.glAttachShader(programObject,vertexShader)
        GLES30.glAttachShader(programObject,fragmentShader)

        GLES30.glBindAttribLocation(programObject,0,"vPosition")
        GLES30.glLinkProgram(programObject)

        GLES30.glGetProgramiv(programObject,GLES30.GL_LINK_STATUS,linked,0)

        if(linked[0]==0){
            Log.e(TAG,"Error linking program:")
            Log.e(TAG,GLES30.glGetProgramInfoLog(programObject))
            GLES30.glDeleteProgram(programObject)
            return
        }

        mProgramObject=programObject

    }

    private var mColorHandle=0

    private var mMVPMatrixHandle=0

    private val colorblue=Color.blue
    private val colorcyan=Color.cyan
    private val colorred=Color.red
    private val colorgray=Color.gray
    private val colorgreen=Color.green
    private val coloryellow=Color.yellow

    public fun draw(mvpMatrix:FloatArray){
        GLES30.glUseProgram(mProgramObject)

        mMVPMatrixHandle=GLES30.glGetUniformLocation(mProgramObject,"uMVPMatrix")
        OpenGl3Render.checkGlError("glGetUniformLocation")

        mColorHandle=GLES30.glGetUniformLocation(mProgramObject,"vColor")

        GLES30.glUniformMatrix4fv(mMVPMatrixHandle,1,false,mvpMatrix,0)
        OpenGl3Render.checkGlError("glUniformMatrix4fv")

        val VERTEX_POS_INDEX=0
        mVertices.position(VERTEX_POS_INDEX)
        GLES30.glVertexAttribPointer(VERTEX_POS_INDEX,3,GLES30.GL_FLOAT,
            false,0,mVertices)
        GLES30.glEnableVertexAttribArray(VERTEX_POS_INDEX)

        var startPos=0
        val verticesPerface=6

        GLES30.glUniform4fv(mColorHandle,1,colorblue,0)
        GLES30.glDrawArrays(GLES30.GL_TRIANGLES,startPos,verticesPerface)
        startPos+=verticesPerface


        GLES30.glUniform4fv(mColorHandle,1,colorcyan,0)
        GLES30.glDrawArrays(GLES30.GL_TRIANGLES,startPos,verticesPerface)
        startPos+=verticesPerface


        GLES30.glUniform4fv(mColorHandle,1,colorred,0)
        GLES30.glDrawArrays(GLES30.GL_TRIANGLES,startPos,verticesPerface)
        startPos+=verticesPerface


        GLES30.glUniform4fv(mColorHandle,1,colorgray,0)
        GLES30.glDrawArrays(GLES30.GL_TRIANGLES,startPos,verticesPerface)
        startPos+=verticesPerface


        GLES30.glUniform4fv(mColorHandle,1,colorgreen,0)
        GLES30.glDrawArrays(GLES30.GL_TRIANGLES,startPos,verticesPerface)
        startPos+=verticesPerface


        GLES30.glUniform4fv(mColorHandle,1,coloryellow,0)
        GLES30.glDrawArrays(GLES30.GL_TRIANGLES,startPos,verticesPerface)
        startPos+=verticesPerface









    }

    companion object {

        private  val size=0.4f
        private val mVerticesData= floatArrayOf(
            -size, size, size
            - size,-size, size,
            size,-size, size,

            size,-size, size,
            size, size, size,
            -size, size, size,


            -size, size, -size,
            -size, -size, -size,
            size, -size, -size,

            -size, size, -size,
            -size, -size, -size,
            -size, -size, size,

            -size, -size, size,
            -size, size, size,
            -size, size, -size,

            -size, -size, size,
            -size, size, size,
            -size, size, -size,


            size, size, -size,
            size, -size, -size,
            size, -size, size,

            size, -size, size,
            size, size, size,
            size, size, -size,


            -size, size, -size,
            -size, size, size,
            size, size, size,

            size, size, size,
            size, size, -size,
            -size, size, -size,


            -size, -size, -size,
            -size, -size, size,
            size, -size, size,

            size, -size, size,
            size, -size, -size,
            -size, -size, -size
        )

        private val vShaderStr=
                """
                    #version 300 es
                    uniform mat4 uMVPMatrix;
                    in vec4 vPosition;
                    void main(){
                        gl_Position=uMVPMatrix*vPosition;
                    }
                """.trimIndent()

        private val fShaderStr=
                """
                    #version 300 es
                    precision mediump float;
                    uniform vec4 vColor;
                    out vec4 fragColor;
                    void main(){
                        fragColor=vColor;
                    }
                """.trimIndent()
        private val TAG=Cube::class.simpleName
    }

}
